# -*- coding: utf-8 -*-
import json
import logging
import os
import random
import time
from traceback import format_exc
import requests
from scrapy.utils.project import get_project_settings
from zc_core.dao.cookie_dao import CookieDao

from abchina.util.aes_util import AesCrypter
from abchina.util.launcher import Launcher
from zc_core.plugins.verify_code import VerifyCode


class ApiLogin(object):
    # 验证码
    validate_code_url = 'https://e.abchina.com/qyjc/site/Account/ValidateCode?_=1552975002920'
    # 登录地址
    login_url = 'https://e.abchina.com/qyjc/site/Account/SignIn'

    def __init__(self):
        settings = get_project_settings()
        self.max_login_retry = settings.get('MAX_LOGIN_RETRY', 2)
        self.accounts = settings.get('ACCOUNTS', [])

    # 优先从缓存中读取，否则登录
    def get_encrypt_and_cookies(self):
        cookie_dao = CookieDao()
        encrypt_cookies = cookie_dao.get_cookie()
        if not encrypt_cookies:
            encrypt_cookies = self.login()
            if encrypt_cookies and self.sec_key and self.sec_iv and self.cookies:
                cookie_dao.save_cookie(encrypt_cookies, expire_time=3600*2)
        return encrypt_cookies

    # 登录操作
    def login(self):
        # 初始化一次
        launcher = Launcher()
        launcher.launch()
        if launcher.sec_iv and launcher.sec_key:
            self.sec_key = launcher.sec_key
            self.sec_iv = launcher.sec_iv
            self.cookies = launcher.cookies
        else:
            raise Exception('ApiLogin初始化失败')
        return self._get_cookies(0)

    # 登录并获取cookie
    def _get_cookies(self, retry):
        # 登录获取
        login_success = self._do_login()
        if not login_success:
            # 失败重试
            if retry <= self.max_login_retry:
                retry = retry + 1
                logging.info('--> 登录失败重试: %s次' % retry)
                return self._get_cookies(retry)
            else:
                logging.info('--> 放弃失败重试: %s次' % retry)
                return dict()

        login_result = {
            'sec_key': self.sec_key,
            'sec_iv': self.sec_iv,
            'cookies': self.cookies,
        }
        logging.info('--> Login Result: %s' % login_result)

        return login_result

    def _do_login(self):
        try:
            # 识别验证码
            code = self._verify_code()
            if code:
                # 随机选择账号
                account = random.choice(self.accounts)
                logging.info('login account: %s' % account)
                # 请求登录
                params = {
                    'LoginName': list(account.keys())[0],
                    'Password': list(account.values())[0],
                    'ValidateCode': code,
                    "InterfaceName": "Account/SignIn"
                }
                timestamp = str(int(round(time.time())))

                # aes
                aes = AesCrypter(self.sec_key, self.sec_iv)
                enc_msg = aes.encrypt(
                    json.dumps(params, separators=(',',':'))
                )
                integrity_hash = aes.hmac_sha1_sign(enc_msg, timestamp.encode())
                proxies = {
                    'http': 'http://182.148.1.220:30186',
                    'https': 'https://182.148.1.220:30186',
                }
                r = requests.post(
                    proxies=proxies,
                    url=self.login_url,
                    data=json.dumps({
                        'EncryptMsg': str(enc_msg, encoding='utf-8')
                    }),
                    headers={
                        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36',
                        'Content-Type': 'application/json;charset=UTF-8',
                        'X-EncryptType': 'encrypt',
                        'X-Timestamp': timestamp,
                        'X-IntegrityHash': integrity_hash,
                    },
                    cookies=self.cookies,
                    timeout=120,
                )

                # 校验
                if r and r.text:
                    logging.info('Login API: %s' % r.text)
                    rs = json.loads(r.text)
                    # 登录失败：验证码错误
                    if rs.get('Code', '') != 0 or rs.get('Message', '') == '验证码错误':
                        return False

                    logging.info('--> 登录成功: %s' % self.cookies)
                    # 敏感过滤
                    for key in self.cookies:
                        if key not in ['BIGipServerpool_ebiz_qyjc', 'GroupPurchaseSessionId', 'BIGipServerpool_ebiz_9000', 'security_session_verify']:
                            self.cookies.pop(key)
                    logging.info('--> 敏感过滤: %s' % self.cookies)
                    return True

            return False
        except Exception as e:
            _ = e
            logging.error(format_exc())
            return False

    def _verify_code(self):
        """
        截取指定元素图片
        :param element: 元素对象
        :return: 无
        """
        """图片保存"""
        response = requests.get(self.validate_code_url, cookies=self.cookies)
        self.cookies.update(response.cookies)
        img = response.content
        settings = get_project_settings()
        base_path = os.path.join(settings.get('OUTPUT_ROOT'), 'verify_code\\')
        if not os.path.exists(base_path):
            os.makedirs(base_path)
        file = os.path.join(base_path, '%s.png' % str(time.strftime('%Y%m%d%H%M%S')))
        with open(file, 'wb') as f:
            f.write(img)

        """保存识别结果"""
        code = VerifyCode().verify(file, code_type='1004')
        if code:
            new_file = os.path.join(base_path, '%s.png' % code)
            os.rename(file, new_file)
            return code


if __name__ == '__main__':
    login = ApiLogin()
    login.login()
